#include "ipcShm.hpp"

static void server()
{
    // 1.通过pathname及proj_id生成标定共享内存的唯一值
    key_t key=ftok(PATHNAME,PROJID);
    if(key<0)
    {
        perror("ftok");
        exit(1);
    }

    // 2.通过key值创建获取共享内存的shmid
    // int shmget(key_t key, size_t size, int shmflg);
    // 只传IPC_CREAT: 不存在则创建之,存在则返回已经存在的共享内存
    // 只传IPC_CREAT+IPC_EXCL: 不存在则创建之,存在则错误返回
    int shmid=shmget(key,SHMSIZE,IPC_CREAT|IPC_EXCL|0666);
    if(shmid<0)
    {
        perror("shmget");
        exit(2);
    }

    fprintf(stdout,"key: %d shmid: %d\n",key,shmid);

    fprintf(stdout,"shmat begin\n");
    //sleep(10);
    // 3.进程地址空间与物理内存块建立映射
    // void *shmat(int shmid, const void *shmaddr, int shmflg);
    void *shm_ptr=shmat(shmid,nullptr,0);
    if(shm_ptr==reinterpret_cast<void*>(-1))
    {
        perror("shmat");
        exit(3);
    }

    // 4.ipc...
    while(true)
    {
        std::cout<<"read begin"<<std::endl;
        std::cout<<static_cast<char*>(shm_ptr)<<std::endl;
        std::cout<<"read end"<<std::endl;
        sleep(1);
    }

    fprintf(stdout,"shmdt begin\n");
    //sleep(10);
    // 5.取消挂接
    int ret=shmdt(shm_ptr);
    if(ret<0)
    {
        perror("shmat");
        exit(4);
    }

    fprintf(stdout,"shmctl begin\n");
    //sleep(10);
    // 6.通过系统调用将shmid对应的共享内存从内核中删除
    // int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    ret=shmctl(shmid,IPC_RMID,nullptr);
    if(ret<0)
    {
        perror("shmat");
        exit(5);
    }
}

int main()
{
    server();
    return 0;
}